{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "08eef9ee",
   "metadata": {},
   "source": [
    "# Robotics, Vision & Control 3e: for Python\n",
    "## Appendices\n",
    "\n",
    "Copyright (c) 2021- Peter Corke"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "39e6a505",
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    from google.colab import output\n",
    "    print('Running on CoLab')\n",
    "    output.enable_custom_widget_manager()\n",
    "    !pip install ipympl\n",
    "    !pip install spatialmath-python\n",
    "    COLAB = True\n",
    "    SWIFT = False\n",
    "except ModuleNotFoundError:\n",
    "    COLAB = False\n",
    "    SWIFT = False\n",
    "from IPython.core.interactiveshell import InteractiveShell\n",
    "InteractiveShell.ast_node_interactivity = \"last_expr_or_assign\"\n",
    "from IPython.display import HTML\n",
    "\n",
    "\n",
    "# add RTB examples folder to the path\n",
    "import sys\n",
    "import os.path\n",
    "import roboticstoolbox as rtb\n",
    "sys.path.append(os.path.join(rtb.__path__[0], 'examples'))\n",
    "\n",
    "# standard imports\n",
    "import numpy as np\n",
    "from scipy import linalg\n",
    "%matplotlib widget\n",
    "import matplotlib.pyplot as plt\n",
    "import math\n",
    "from math import pi\n",
    "np.set_printoptions(\n",
    "    linewidth=120, formatter={\n",
    "        'float': lambda x: f\"{0:8.4g}\" if abs(x) < 1e-10 else f\"{x:8.4g}\"})\n",
    "np.random.seed(0)\n",
    "from spatialmath import *\n",
    "from spatialmath.base import *\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78d7dc48",
   "metadata": {},
   "source": [
    "# B Linear Algebra\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6978610",
   "metadata": {},
   "source": [
    "## B.2 Matrices\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4723930",
   "metadata": {},
   "source": [
    "### B.2.1 Square Matrices\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67cb4ff6",
   "metadata": {},
   "source": [
    "This demo shows a red unit vector rotating like the minute hand of a clock.  The blue vector is its linear transformation.  Twice per revolution the vectors are parallel and the red vector on those occasions are eigenvectors.  The relative scale of the blue vector is the eigenvalue.\n",
    "\n",
    "Change the four numbers to see what happens with a different transformation matrix, they are the four matrix elements given row-wise.\n",
    "\n",
    "Hit the interrupt button to stop the animation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e36c5a96",
   "metadata": {},
   "outputs": [],
   "source": [
    "%run -m eigdemo 1 2 3 4"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0f91717",
   "metadata": {},
   "source": [
    "# C Geometry\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcacdc7c",
   "metadata": {},
   "source": [
    "## C.1 Euclidean Geometry\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf3373b1",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "source": [
    "### C.1.2 Lines\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d70bced",
   "metadata": {},
   "source": [
    "#### C.1.2.2 Lines in 3D and Plücker Coordinates\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e1f20cae",
   "metadata": {},
   "outputs": [],
   "source": [
    "P = [2, 3, 4]; Q = [3, 5, 7];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e839250c",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = Line3.Join(P, Q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cda46d17",
   "metadata": {},
   "outputs": [],
   "source": [
    "L.v.T\n",
    "L.w.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4ad38a8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "L.skew()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b322af7",
   "metadata": {},
   "outputs": [],
   "source": [
    "plotvol3([-5, 5]);\n",
    "L.plot(\"b\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98262495",
   "metadata": {},
   "outputs": [],
   "source": [
    "L.point([0, 1, 2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ebf71c3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "[x, d] = L.closest_to_point([1, 2, 3])\n",
    "x\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6429840f",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "outputs": [],
   "source": [
    "p, _ = L.intersect_plane([0, 0, 1, 0])\n",
    "p"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12023edb",
   "metadata": {},
   "source": [
    "### C.1.4 Ellipses and Ellipsoids\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c2da6ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "E = np.array([[1, 1], [1, 2]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5a9fecdf",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_ellipse(E, [0, 0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "efd33949",
   "metadata": {},
   "outputs": [],
   "source": [
    "e, v = np.linalg.eig(E)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "478c1ddc",
   "metadata": {},
   "source": [
    "the eigenvalues are"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b11e15d",
   "metadata": {},
   "outputs": [],
   "source": [
    "e"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea9369e6",
   "metadata": {},
   "source": [
    "and the eigenvectors are the columns of"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "04227ab9",
   "metadata": {},
   "outputs": [],
   "source": [
    "v"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2648e8b",
   "metadata": {},
   "source": [
    "and the radii, the half-lengths of the major and minor axes are"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bac44e03",
   "metadata": {},
   "outputs": [],
   "source": [
    "r = 1 / np.sqrt(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d49629eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_arrow((0, 0), v[:,0]*r[0], color=\"r\", width=0.02);\n",
    "plot_arrow((0, 0), v[:,1]*r[1], color=\"b\", width=0.02);\n",
    "plt.gca().set_aspect('equal', 'box')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "75a2b89b",
   "metadata": {},
   "source": [
    "and the orientation of the major axis, in degrees, is"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "86e4588e",
   "metadata": {},
   "outputs": [],
   "source": [
    "np.rad2deg(np.arctan2(v[1, 0], v[0, 0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "224add22",
   "metadata": {},
   "source": [
    "### C.1.4.1 Drawing an Ellipse\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d0ce8dc1",
   "metadata": {},
   "outputs": [],
   "source": [
    "E = np.array([[1, 1], [1, 2]]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "920af014",
   "metadata": {},
   "outputs": [],
   "source": [
    "th = np.linspace(0, 2*pi, 50);\n",
    "y = np.vstack([np.cos(th), np.sin(th)]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7276c1c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = linalg.sqrtm(np.linalg.inv(E)) @ y;\n",
    "plt.figure()\n",
    "plt.plot(x[0, :], x[1, :], '.');"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1266a045",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_ellipse(E, [0, 0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f0afa12",
   "metadata": {},
   "source": [
    "#### C.1.4.2 Fitting an Ellipse to Data\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "942289fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "rng = np.random.default_rng(0);\n",
    "# create 200 random points inside the ellipse\n",
    "x = [];\n",
    "while len(x) < 200: \n",
    "  p = rng.uniform(low=-2, high=2, size=(2,1))\n",
    "  if np.linalg.norm(p.T @ E @ p) <= 1:\n",
    "    x.append(p)\n",
    "x = np.hstack(x);  # create 2 x 50 array\n",
    "plt.plot(x[0, :], x[1, :], \"k.\"); # plot them\n",
    "# compute the moments\n",
    "m00 = mpq_point(x, 0, 0);\n",
    "m10 = mpq_point(x, 1, 0);\n",
    "m01 = mpq_point(x, 0, 1);\n",
    "xc = np.c_[m10, m01] / m00;\n",
    "# compute the central second moments\n",
    "x0 = x - xc.T;\n",
    "u20 = mpq_point(x0, 2, 0);\n",
    "u02 = mpq_point(x0, 0, 2);\n",
    "u11 = mpq_point(x0, 1, 1);\n",
    "# compute inertia tensor and ellipse matrix\n",
    "J = np.array([[u20, u11], [u11, u02]]);\n",
    "E_est = m00 / 4 * np.linalg.inv(J);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3acfc499",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f'E:\\n {E}')\n",
    "print(f'Eest:\\n {E_est}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "507120c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(x[0, :], x[1, :], \"k.\"); # plot data points\n",
    "plot_ellipse(E_est, [0, 0], \"r\")          # plot fitted ellipse"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e838e8af",
   "metadata": {},
   "source": [
    "## C.2 Homogeneous Coordinates\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b3a294a",
   "metadata": {},
   "source": [
    "### C.2.1 Two Dimensions\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4457afc4",
   "metadata": {},
   "source": [
    "#### C.2.1.1 Points and lines\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3ec28b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "l1 = [1, -1, 0];\n",
    "l2 = [1, -1, -1];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1a508a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "plotvol2([-2, 2, -2, 2], new=True)\n",
    "plot_homline(l1, \"b\");\n",
    "plot_homline(l2, \"r\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72c5edc2",
   "metadata": {},
   "outputs": [],
   "source": [
    "np.cross(l1, l2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6777a8b2",
   "metadata": {},
   "source": [
    "# E Linearizations, Jacobians and Hessians"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96d7a10c",
   "metadata": {},
   "source": [
    "## E.4 Deriving Jacobians\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28d6791c",
   "metadata": {},
   "outputs": [],
   "source": [
    "zrange = lambda xi, xv, w: np.array([\n",
    "           np.linalg.norm(xi - xv[:2]) + w[0],\n",
    "           np.arctan((xi[1] - xv[1]) / (xi[0] - xv[0])) -xv[2] + w[1]]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f39f7b5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "xv = np.r_[1, 2, pi/3]; xi = np.r_[10, 8]; w = np.r_[0, 0];\n",
    "h0 = zrange(xi, xv, w)\n",
    "d = 0.001;\n",
    "J = np.column_stack([\n",
    "       zrange(xi, xv + [d, 0, 0], w) - h0,\n",
    "       zrange(xi, xv + [0, d, 0], w) - h0,\n",
    "       zrange(xi, xv + [0, 0, d], w) - h0\n",
    "                    ]) / d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2dc79849",
   "metadata": {},
   "outputs": [],
   "source": [
    "numjac(lambda x: zrange(xi, x, w), xv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "908ade06",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sympy import Matrix, MatrixSymbol, sqrt, atan, simplify, pycode\n",
    "xi = MatrixSymbol(\"xi\", 2, 1)\n",
    "xv = MatrixSymbol(\"xv\", 3, 1)\n",
    "w = Matrix([0, 0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92e0c1d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "zrange = lambda xi, xv, w: Matrix([\n",
    "            sqrt((xi[0] - xv[0])**2 + (xi[1] - xv[1])**2) + w[0],\n",
    "            atan((xi[1] - xv[1]) / (xi[0] - xv[0])) -xv[2] + w[1]]);\n",
    "z = zrange(xi, xv, w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c72fcd78",
   "metadata": {},
   "outputs": [],
   "source": [
    "J = z.jacobian(xv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d50ee7a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "J.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5226019",
   "metadata": {},
   "source": [
    "# F Solving Systems of Equations\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e261cef2",
   "metadata": {},
   "source": [
    "## F.1 Linear Problems\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5c5d3133",
   "metadata": {},
   "source": [
    "### F.1.1 Nonhomogeneous Systems\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "36a4a78e",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, -2], [1, 1]]);\n",
    "b = np.array([[8], [5]]);\n",
    "x = linalg.solve(A, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06480edf",
   "metadata": {},
   "source": [
    "# G Gaussian Random Variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "582836c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.linspace(-6, 6, 500);\n",
    "plt.figure()\n",
    "plt.plot(x, gauss1d(0, 1, x), \"r\");\n",
    "plt.plot(x, gauss1d(0, 2**2, x), \"b--\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b28748ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "mu = 10; sigma = 2;\n",
    "g = np.random.normal(loc=mu, scale=sigma, size=(100,))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3a3c6caf",
   "metadata": {},
   "outputs": [],
   "source": [
    "x, y = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100));\n",
    "P = np.diag([1, 2])**2;\n",
    "g = gauss2d([0, 0], P, x, y);\n",
    "ax = ax = plotvol3();\n",
    "ax.plot_surface(x, y, g);\n",
    "ax.contour(x, y, g, zdir=\"z\", offset=-0.05);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "54182d82",
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.stats.distributions import chi2\n",
    "chi2.ppf(0.5, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80545342",
   "metadata": {},
   "source": [
    "# H Kalman Filter\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff272e4d",
   "metadata": {},
   "source": [
    "## H.2 Nonlinear Systems -- Extended Kalman Filter\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cb9492d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.random.normal(5, 2, size=(1_000_000,));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "805f1d30",
   "metadata": {},
   "outputs": [],
   "source": [
    "y = (x + 2)**2 / 4;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "076914c2",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "outputs": [],
   "source": [
    "plt.hist(y, bins=200, density=True, histtype=\"step\");"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "000b8366",
   "metadata": {},
   "source": [
    "# I Graphs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b625fbe6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pgraph\n",
    "g = pgraph.UGraph()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5a121e53",
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(0)  # ensure repeatable results\n",
    "for i in range(5):\n",
    "  g.add_vertex(np.random.rand(2));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5aefda27",
   "metadata": {},
   "outputs": [],
   "source": [
    "g[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5009c67e",
   "metadata": {},
   "outputs": [],
   "source": [
    "g[\"#1\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d6b6006",
   "metadata": {},
   "outputs": [],
   "source": [
    "g.add_edge(g[0], g[1]);\n",
    "g.add_edge(g[0], g[2]);\n",
    "g.add_edge(g[0], g[3]);\n",
    "g.add_edge(g[1], g[2]);\n",
    "g.add_edge(g[1], g[3]);\n",
    "g.add_edge(g[3], g[4]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a7ffac93",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(g)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "938b62ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "g.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7bd82a36",
   "metadata": {},
   "outputs": [],
   "source": [
    "g[1].adjacent()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21f7f274",
   "metadata": {},
   "outputs": [],
   "source": [
    "g[1].edges()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "450fe73f",
   "metadata": {},
   "outputs": [],
   "source": [
    "g[1].edges()[0].endpoints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "625f510d",
   "metadata": {},
   "outputs": [],
   "source": [
    "g[1].edges()[0].cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e883071",
   "metadata": {},
   "outputs": [],
   "source": [
    "g.closest((0.5, 0.5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8bc7fbd3",
   "metadata": {},
   "outputs": [],
   "source": [
    "path, length, _ = g.path_Astar(g[2], g[4])\n",
    "path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cc48d27",
   "metadata": {},
   "outputs": [],
   "source": [
    "length"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f922a853",
   "metadata": {},
   "source": [
    "# J Peak Finding\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21f13380",
   "metadata": {},
   "source": [
    "## J.1 1D Signal\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d68a8e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "from machinevisiontoolbox import mvtb_load_matfile, findpeaks, findpeaks2d\n",
    "y = mvtb_load_matfile(\"data/peakfit.mat\")[\"y\"];\n",
    "plt.plot(y, \"-o\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e2125e1e",
   "metadata": {},
   "outputs": [],
   "source": [
    "k = np.argmax(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d3b780a",
   "metadata": {},
   "outputs": [],
   "source": [
    "y[k]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e329128c",
   "metadata": {},
   "outputs": [],
   "source": [
    "k, ypk = findpeaks(y)\n",
    "k\n",
    "ypk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b286dc1c",
   "metadata": {},
   "outputs": [],
   "source": [
    "ypk[1] / ypk[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87f0f8d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "findpeaks(y, interp=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "753c37ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "findpeaks(y, scale=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2a9e2bf",
   "metadata": {},
   "source": [
    "## J.2 2D Signal\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d38de617",
   "metadata": {},
   "outputs": [],
   "source": [
    "img = mvtb_load_matfile(\"data/peakfit.mat\")[\"image\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5a6212a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "k = np.argmax(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3aa667ea",
   "metadata": {},
   "outputs": [],
   "source": [
    "img.ravel()[k]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "390033f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "np.unravel_index(k, img.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f1d12ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "xy = findpeaks2d(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f5a502e3",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "outputs": [],
   "source": [
    "xy = findpeaks2d(img, interp=True)"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": "Python 3.8.5 ('dev')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  },
  "vscode": {
   "interpreter": {
    "hash": "b7d6b0d76025b9176285a6442c3dd6dd39bcfe7241029b7898b7106bd5e9b472"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
